#!/usr/bin/env python
# -*- coding:utf-8 -*-
# Author: Justin

from src.acquisition.slice.patches import get_roi, get_seeds
from src.acquisition.slice.patches import parameter as pr


class Patch(object):
    def __init__(self):
        self.seeds = []

    # src_image是等比例缩小后的图fullImage，distance是EXTRACT_PATCH_DIST
    def get_roi_seeds(self, src_image, distance):
        # 对fullImage做处理
        # 感觉这里roi_img就是个膨胀和腐蚀后的二值图像
        roi_img = get_roi(src_image)
        # 返回对二值图像进一步处理后的一些非0点（白色），YX两坐标，代表行列
        self.seeds = get_seeds(roi_img, distance)
        return

    # 自己后续改的一段代码，可以写出对应点的txt文件
    # src_image是等比例缩小后的图fullImage，distance是EXTRACT_PATCH_DIST
    def get_roi_seeds_and_save_txt(self, src_image, distance,map_txt_path = None,if_write_txt = False):
        # 对fullImage做处理
        # 感觉这里roi_img就是个膨胀和腐蚀后的二值图像
        roi_img = get_roi(src_image,map_txt_path,if_write_txt)
        # 返回对二值图像进一步处理后的一些非0点（白色），YX两坐标，代表行列
        self.seeds = get_seeds(roi_img, distance)
        return

    # x is col, y is row
    # 判断切出的图片是否为癌症切片
    def detect_cancer_patch(self, mask_img, x, y, patch_width):
        half = int(patch_width / 2)
        # 取mask_img里某个x,y点的上下左右half个点的范围，即(2*half)的平方个点的面积，以此来确定是不是癌
        sub_m = mask_img[y - half: y + half, x - half: x + half]
        # 应该是将sub_m面里的值全加起来？
        total = sub_m.sum()
        # 和上述x,y所标出的面积相除，得出的值若大于1，则为癌症切块
        r = total / (patch_width * patch_width)
        return r > 0.85

    # 正式切割图片
    # patch_width就是PATCH_SIZE_HIGH
    # 这里的scale就是EXTRACT_SCALE
    def extract_patches(self, slide, mask_img, scale, patch_width):
        i = 12000000
        for (x, y) in self.seeds:
            # （貌似）mask_img为根据标注弄出来的区域，xy是原始图像进行开闭运算后的出来的白色区域
            isCancer = self.detect_cancer_patch(mask_img, x, y, pr.PATCH_SIZE_LOW)
            # AMPLIFICATION_SCALE就是PATCH_SIZE_HIGH/PATCH_SIZE_LOW
            xx = int(pr.AMPLIFICATION_SCALE * x)
            yy = int(pr.AMPLIFICATION_SCALE * y)

            # 应该是根据之前对缩小后的图进行一系列处理后得到的非0坐标，乘以AMPLIFICATION_SCALE后，找到原图上万像素点中的某个位置的一定长宽的切块
            # xx,yy应该是原图中的左上角的X，Y坐标，patch_width为其图片块大小
            patch_data = slide.get_image_block(scale, xx, yy, patch_width, patch_width, True)
            #filename = "/{0}_{1:0>6}_{2:0>6}.jpg".format(slide.get_id(), xx, yy)
            # filename = str(i) + '.jpg'
            # i+=1
            if isCancer:
                filename = str(i) + '.jpg'
                i += 1
                patch_data.tofile(pr.PATCH_PATH_CANCER + filename)

            # 原本是注释掉的

            else:
                filename = str(i) + '.jpg'
                i += 1
                patch_data.tofile(pr.PATCH_PATH_NORMAL + filename)


        return

    # 切割图片的同时，保存每张图片在缩略图上的对应点
    # 对应点这里我设置它让其不经过判断直接输出，因为我想让标注区域内的图片都生成出来
    # 【去掉了isCancer的判断】
    def extract_patches_and_save_txt(self, slide, mask_img, scale, patch_width, map_txt_path = None, if_write_txt=False):
        all_point = []
        pos = mask_img.nonzero()
        pos_num = len(pos[0])
        # for (x, y) in self.seeds:
        for i in range(pos_num):
            single_point = []
            x = pos[1][i]
            y = pos[0][i]


            # （貌似）mask_img为根据标注弄出来的区域，xy是原始图像进行开闭运算后的出来的白色区域
            # isCancer = self.detect_cancer_patch(mask_img, x, y, pr.PATCH_SIZE_LOW)
            # AMPLIFICATION_SCALE就是PATCH_SIZE_HIGH/PATCH_SIZE_LOW
            xx = int(pr.AMPLIFICATION_SCALE * x)
            yy = int(pr.AMPLIFICATION_SCALE * y)

            # 应该是根据之前对缩小后的图进行一系列处理后得到的非0坐标，乘以AMPLIFICATION_SCALE后，找到原图上万像素点中的某个位置的一定长宽的切块
            # xx,yy应该是原图中的左上角的X，Y坐标，patch_width为其图片块大小
            patch_data = slide.get_image_block(scale, xx, yy, patch_width, patch_width, True)
            filename = str(i+1) + '.jpg'
            patch_data.tofile(pr.PATCH_PATH + filename)

            # ********************自己加的一段写出区域坐标的代码********************
            single_point.append(x)
            single_point.append(y)
            single_point.append(i+1)
            all_point.append(single_point)


            # ********************自己加的一段写出区域坐标的代码********************

        # ********************自己加的一段写出区域坐标的代码********************
        if if_write_txt:
            self.save_result_roi_txt(all_point,map_txt_path)
        # ********************自己加的一段写出区域坐标的代码********************

        return

    # 自己加的一段写出区域坐标的代码
    # 输出最后输出图片在缩略图上对应的xy点
    def save_result_roi_txt(self,result,output_path):
        txt_file = open(output_path, 'w')
        result_num = len(result)
        for i in range(result_num):
            txt_file.write(str(result[i][0])+','+str(result[i][1])+','+str(result[i][2])+'\n')
        txt_file.close()